package com.wanlian.socketserver.Device.Handler;

import com.wanlian.json.JsonStringUtil;
import com.wanlian.netty.model.Address;
import com.wanlian.netty.model.ResultInfo;
import com.wanlian.netty.model.Session;
import com.wanlian.netty.msg.*;
import com.wanlian.socketserver.Device.DeviceOnlineChecker;
import com.wanlian.socketserver.Device.worker.DeviceServerWorker;
import com.wanlian.util.StringUtil;
import com.wanlian.util.Utils;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * Handles a server-side channel.
 */
public class DeviceServerHandler extends ChannelInboundHandlerAdapter { // (1)
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIP = insocket.getAddress().getHostAddress();
        int port = insocket.getPort();
        try {
            PeerMsg peerMsg = (PeerMsg) msg;
            String msgType = peerMsg.getBaseMsg().getType();
            if (msgType.equals(MsgType.REGISTER)) {
                // TODO:加入到网络时需要验证地址信息
                Address address = JsonStringUtil.readValue(peerMsg.getBaseMsg().getContent(), Address.class);
                if (StringUtil.hasValue(clientIP)) {
                    address.setIp(clientIP);
                }
                address.setPort(port);
                Session session = new Session(ctx.channel());
                session.setId(ctx.channel().id());
                session.setPublicKey(address.getPublickey());
                session.setAddress(address);
                if (DeviceServerWorker.sessionPool.isExist(address.getPublickey())) {
                    if (peerMsg.getBaseMsg().isbNew()) {
                        DeviceServerWorker.sendDataByKey(address.getPublickey(), new PeerOutMsg());
                        String response = " register success";
                        System.out.println(address.getPublickey() + response);
                        DeviceOnlineChecker.setOnline(address.getPublickey(), address.getVersion());
                        DeviceServerWorker.sessionPool.changeSession(session);
                        DeviceServerWorker.replyRegister(address.getPublickey());
                    } else {
                        //add type
                        ResultMsg resultMsg = new ResultMsg(MsgType.REGISTER);
                        resultMsg.setClientId(DeviceServerWorker.getServer().getPublicKey());
                        resultMsg.setTagClientId(address.getPublickey());
                        ResultInfo info = new ResultInfo(false, "终端已注册");
                        resultMsg.setResultInfo(info);
                        sendPeerMsg(ctx, resultMsg);
                    }
                } else {
                    String response = " register success";
                    System.out.println(address.getPublickey() + response);
                    DeviceOnlineChecker.setOnline(address.getPublickey(), address.getVersion());
                    DeviceServerWorker.sessionPool.addSession(session);
                    DeviceServerWorker.replyRegister(address.getPublickey());
                }
            } else {
                String clientId = peerMsg.getBaseMsg().getClientId();
                if (!DeviceServerWorker.sessionPool.isExist(clientId)) {
                    ResultInfo info = new ResultInfo(false, "终端未注册");
                    ResultMsg resultMsg = new ResultMsg(MsgType.REGISTER);
                    resultMsg.setResultInfo(info);
                    sendPeerMsg(ctx, resultMsg);
                } else {
                    PeerMsg copyMsg = peerMsg.deepCopyMsg();
                    PeerMsgQueue.add(copyMsg);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }


    private void sendPeerMsg(ChannelHandlerContext ctx, BaseMsg baseMsg) {
        PeerMsg psg = new PeerMsg(baseMsg);
        ctx.writeAndFlush(psg);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        try {
            DeviceServerWorker.removeByChannelId(ctx.channel().id());
            System.out.println(ctx.channel().id() + "  caught exception server");
            ctx.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}